x86/emulator: workaround for AMD erratum 573
authorJan Beulich <jbeulich@suse.com>
Fri, 16 Dec 2011 14:45:40 +0000 (15:45 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 16 Dec 2011 14:45:40 +0000 (15:45 +0100)
The only cases where we might end up emulating fsincos (as any other
x87 operations without memory operands) are
- when a HVM guest is in real mode (not applicable on AMD)
- between two half page table updates in PAE mode (unlikely, and not
  doing the emulation here does affect only performance, not
  correctness)
- when a guest maliciously (or erroneously) modifies an (MMIO or page
  table update) instruction under emulation (unspecified behavior)

Hence, in order to avoid the erratum to cause harm to the entire host,
don't emulate fsincos on the affected AMD CPU families.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
tools/tests/x86_emulator/x86_emulate.c
xen/arch/x86/x86_emulate.c
xen/arch/x86/x86_emulate/x86_emulate.c
xen/include/asm-x86/amd.h

index 9e1b1244103703e47d8ac061ba55eb65619abaa1..0306f8ebc6d5ead435c708277c1013cb1d6b7c09 100644 (file)
@@ -9,5 +9,7 @@ typedef bool bool_t;
 
 #define BUG() abort()
 
+#define cpu_has_amd_erratum(nr) 0
+
 #include "x86_emulate/x86_emulate.h"
 #include "x86_emulate/x86_emulate.c"
index fbf740efeea16160e868adef9ba9663c8cb3b4e1..91f524fc873501c028564bb5579f84ca74a0d64a 100644 (file)
  */
 
 #include <asm/x86_emulate.h>
+#include <asm/processor.h> /* current_cpu_info */
+#include <asm/amd.h> /* cpu_has_amd_erratum() */
 
 /* Avoid namespace pollution. */
 #undef cmpxchg
+#undef cpuid
+
+#define cpu_has_amd_erratum(nr) \
+        cpu_has_amd_erratum(&current_cpu_data, AMD_ERRATUM_##nr)
 
 #include "x86_emulate/x86_emulate.c"
index d6eeb6562a295885fa4b9847ae3a37b1979c8f84..c7489276a8698fbc5366d2b2aacf0c76810a38ad 100644 (file)
@@ -2761,6 +2761,9 @@ x86_emulate(
     case 0xd9: /* FPU 0xd9 */
         switch ( modrm )
         {
+        case 0xfb: /* fsincos */
+            fail_if(cpu_has_amd_erratum(573));
+            /* fall through */
         case 0xc0 ... 0xc7: /* fld %stN */
         case 0xc8 ... 0xcf: /* fxch %stN */
         case 0xd0: /* fnop */
@@ -2786,7 +2789,6 @@ x86_emulate(
         case 0xf8: /* fprem */
         case 0xf9: /* fyl2xp1 */
         case 0xfa: /* fsqrt */
-        case 0xfb: /* fsincos */
         case 0xfc: /* frndint */
         case 0xfd: /* fscale */
         case 0xfe: /* fsin */
index d7fb1a5b53a5fd3115f93c9ee4245043f1ddc9a3..2ff818872f3f7d49637b8bff4ac8d70249381d23 100644 (file)
     AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf),    \
                        AMD_MODEL_RANGE(0x12, 0x0, 0x0, 0x1, 0x0))
 
+#define AMD_ERRATUM_573                                                        \
+    AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x0f, 0x0, 0x0, 0xff, 0xf),     \
+                       AMD_MODEL_RANGE(0x10, 0x0, 0x0, 0xff, 0xf),     \
+                       AMD_MODEL_RANGE(0x11, 0x0, 0x0, 0xff, 0xf),     \
+                       AMD_MODEL_RANGE(0x12, 0x0, 0x0, 0xff, 0xf))
+
 struct cpuinfo_x86;
 int cpu_has_amd_erratum(const struct cpuinfo_x86 *, int, ...);